﻿using DNFImagePacks2Manager.Helpers;
using System.Collections.Generic;
using System.IO;
using Windows.Graphics.Imaging;

namespace DNFImagePacks2Manager.NPK
{
    public class ImageBitmapFile : ImageFile
    {
        public bool IsCompress { get; set; } = false;
        public int ImageWidth { get; set; }
        public int ImageHeight { get; set; }
        public int ImageSize { get; set; }
        public int PositionX { get; set; } = 0;
        public int PositionY { get; set; } = 0;
        public int FrameWidth { get; set; }
        public int FrameHeight { get; set; }

        public ColorPanel? ColorPanel { get; set; }

        public ImageBitmapFile(BinaryReader reader, ImageType type, ColorPanel? colorPanel = null) : base(type)
        {
            ColorPanel = colorPanel;

            byte[] compressBytes = reader.ReadBytes(4);
            byte[] imageWidthBytes = reader.ReadBytes(4);
            byte[] imageHeightBytes = reader.ReadBytes(4);
            byte[] imageSizeBytes = reader.ReadBytes(4);
            byte[] positionXBytes = reader.ReadBytes(4);
            byte[] positionYBytes = reader.ReadBytes(4);
            byte[] frameWidthBytes = reader.ReadBytes(4);
            byte[] frameHeightBytes = reader.ReadBytes(4);

            IsCompress = ByteHelper.Bytes2Int(compressBytes) == 0x06;
            ImageWidth = ByteHelper.Bytes2Int(imageWidthBytes);
            ImageHeight = ByteHelper.Bytes2Int(imageHeightBytes);
            ImageSize = ByteHelper.Bytes2Int(imageSizeBytes);
            PositionX = ByteHelper.Bytes2Int(positionXBytes);
            PositionY = ByteHelper.Bytes2Int(positionYBytes);
            FrameWidth = ByteHelper.Bytes2Int(frameWidthBytes);
            FrameHeight = ByteHelper.Bytes2Int(frameHeightBytes);
        }

        public ImageBitmapFile(SoftwareBitmap bitmap) : base(new ImageType(0x10))
        {
            byte[]? bytes = ImageHelper.ConvertSoftwareBitmapToPixelBytesAsync(bitmap, out int width, out int height);
            if (bytes != null)
            {
                bytes = ZLibHelper.CompressZlib(bytes);
                DataBytes = bytes;

                IsCompress = true;
                ImageSize = bytes.Length;
                ImageWidth = width;
                ImageHeight = height;
                FrameWidth = width;
                FrameHeight = height;
            }
        }

        public ImageBitmapFile(byte[] bytes, int width, int height, int frameWidth, int frameHeight, int positionX, int positionY) : base(new ImageType(0x10))
        {
            if (bytes != null)
            {
                bytes = ZLibHelper.CompressZlib(bytes);
                DataBytes = bytes;

                IsCompress = true;
                ImageSize = bytes.Length;
                ImageWidth = width;
                ImageHeight = height;
                FrameWidth = frameWidth;
                FrameHeight = frameHeight;
                PositionX = positionX;
                PositionY = positionY;
            }
        }

        public bool ValidateSize(int fullSize = 0, int bitCount = 0)
        {
            if (fullSize == 0)
            {
                if (IsCompress)
                {
                    return false;
                }
                else
                {
                    fullSize = ImageSize;
                }
            }
            if (bitCount == 0) {
                bitCount = Type.TypeCode == 0x10 ? 4 : 2;
            }
            return fullSize / bitCount / ImageWidth == ImageHeight;
        }

        public static int GetCompressCode(bool isCompress)
        {
            if (isCompress)
            {
                return 0x06;
            }
            else
            {
                return 0x05;
            }
        }

        public int GetCompressCode()
        {
            return GetCompressCode(IsCompress);
        }

        public override int GetSize()
        {
            return ImageSize;
        }

        public override bool IsCompressed()
        {
            return IsCompress;
        }

        public byte[] GetDataBytes()
        {
            byte[] bytes = DataBytes;
            if (IsCompressed())
            {
                bytes = ZLibHelper.DecompressZlib(bytes);
            }
            byte[] data;
            if (ColorPanel == null)
            {
                data = bytes;
            }
            else
            {
                data = ColorPanel.ReadImageBytes([.. bytes]);
            }
            return data;
        }

        public SoftwareBitmap? GetPreviewImage()
        {
            if (DataBytes.Length > 0) {
                byte[] data = GetDataBytes();

                int bitCount;
                int type;
                if (ColorPanel == null)
                {
                    bitCount = 0;
                    type = Type.TypeCode;
                }
                else
                {
                    bitCount = 4;
                    type = 0x10;
                }
                if (ValidateSize(data.Length, bitCount))
                {
                    return ImageHelper.ConvertBitmapToSoftwareBitmap(data, ImageWidth, ImageHeight, type);
                }
            }
            return null;
        }

        public override byte[] GetIndexBytes()
        {
            List<byte> bytes = [];
            bytes.AddRange(Type.GetBytes());
            bytes.AddRange(ByteHelper.IntList2Bytes([
                GetCompressCode(),
                ImageWidth,
                ImageHeight,
                ImageSize,
                PositionX,
                PositionY,
                FrameWidth,
                FrameHeight
                ]));
            return [.. bytes];
        }
    }
}
